package com.simpou.commons.utils.file;

import com.simpou.commons.utils.TestsConstants;
import com.simpou.commons.utils.tests.TestRunner;
import com.simpou.commons.utils.tests.annot.ClassTest;
import com.simpou.commons.utils.tests.annot.TestOrder;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.w3c.dom.Element;
import org.xml.sax.SAXParseException;

import java.io.File;
import java.security.InvalidParameterException;
import java.util.Set;
import java.util.UUID;

import static org.junit.Assert.*;


@ClassTest(XMLHelper.class)
@RunWith(TestRunner.class)
public class XMLHelperITCase {
    private static XMLHelper helper;

    @BeforeClass
    public static void setUpClass() throws Exception {
        String xmlPath = TestsConstants.RESOURCES_TEST_DIR +
                "XMLHelperTest.xml";
        helper = new XMLHelper(xmlPath);
    }

    @Test
    public void testGetElementRoot() {
        Element root = helper.getElementRoot();
        assertEquals("root", root.getNodeName());
    }

    @Test
    public void testGetElementsByName() {
        Element element;
        String attribute;

        Set<Element> elements = helper.getElementsByName(helper.getElementRoot(),
                "subsubroot");
        assertEquals(3, elements.size());
        //TODO pensar numa forma de testar sem usar posicoes
/*
        element = elements.get(1);
        attribute = element.getAttribute("id");
        assertEquals("", attribute);

        element = elements.get(2);
        attribute = element.getAttribute("id");
        assertEquals("2", attribute);

        element = elements.get(0);
        attribute = element.getAttribute("id");
        assertEquals("1", attribute);

        //testGetSubElementsValues
        List<String> values = helper.getSubElementsValues(element, "element");
        assertEquals(3, values.size());
        assertEquals("value 1", values.get(0));
        assertEquals("value 2", values.get(1));
        assertEquals("value 3", values.get(2));

        // elemento não presente
        elements = helper.getElementsByName(helper.getElementRoot(), "noexists");
        assertEquals(0, elements.size());
*/
    }

    @Test
    public void testGetSubElementsValues() {
        //testGetElementsByName
    }

    @Test
    public void testFromXML() throws Exception {
        //testToXML
    }

    @Test
    public void testToXML() throws Exception {
        boolean deleted;

        Phone phone = new Phone();
        phone.setDdd(55);
        phone.setNumber("5555 5555");

        Person jonas = new Person();
        jonas.setName("Jonas Pereira");
        jonas.setEmail("jonasalvesap@gmail.com");
        jonas.setPhone(phone);

        String xmlFilePath = PropertyHelper.getTempDir() + "xmlHelperTest" +
                UUID.randomUUID() + ".xml";

        if (FileHelper.exists(xmlFilePath)) {
            deleted = FileHelper.delete(xmlFilePath);

            if (!deleted) {
                fail();
            }
        }

        assertFalse(FileHelper.exists(xmlFilePath));
        XMLHelper.toXML(xmlFilePath, jonas, false);
        assertTrue(FileHelper.exists(xmlFilePath));

        Person person = XMLHelper.fromXML(xmlFilePath, Person.class);
        assertEquals(jonas.getName(), person.getName());
        assertEquals(jonas.getEmail(), person.getEmail());
        assertEquals(jonas.getPhone().getDdd(), person.getPhone().getDdd());
        assertEquals(jonas.getPhone().getNumber(), person.getPhone().getNumber());

        // atribuição a objeto não coerente com o XML
        try {
            Boolean objInvalid = XMLHelper.fromXML(xmlFilePath, Boolean.class);
            fail("Invalid object accepted.");
        } catch (InvalidParameterException ipe) {
        }

        deleted = FileHelper.delete(xmlFilePath);

        if (!deleted) {
            fail();
        }

        assertFalse(FileHelper.exists(xmlFilePath));
    }

    @Test
    @TestOrder(1)
    public void testTransform_byteArr_File() throws Exception {
        final File xslFile = FileHelper.getResourceFile("XMLHelperTest.xsl");
        final byte[] xmlContent = FileHelper.read(FileHelper.getResourceFile("XMLHelperTest.xml"));
        final String out = FileHelper.read(FileHelper.getResourceFile("XMLHelperTest.trans").getAbsolutePath());
        final String transformed = new String(XMLHelper.transform(xmlContent, xslFile));
        assertEquals(out, transformed.trim());

        final byte[] xslContent = FileHelper.read(xslFile);
        final String transformed2 = new String(XMLHelper.transform(xmlContent, xslContent));
        assertEquals(out, transformed2.trim());
    }

    @Test
    @TestOrder(1)
    public void testTransform_byteArr_byteArr() throws Exception {
        //testTransform_byteArr_File
    }

        @Test
    @TestOrder(2)
    public void testTransform_File_File() throws Exception {
        final File xslFile = FileHelper.getResourceFile("XMLHelperTest.xsl");
        final File xmlFile = FileHelper.getResourceFile("XMLHelperTest.xml");
        final String out = FileHelper.read(FileHelper.getResourceFile("XMLHelperTest.trans").getAbsolutePath());
        final String transformed = new String(XMLHelper.transform(xmlFile, xslFile));
        assertEquals(out, transformed.trim());
    }

    @Test
    public void testValidate_byteArr_File() throws Exception {
        final File xsdFile = FileHelper.getResourceFile("XMLHelperTest.xsd");
        final byte[] xsmFile = FileHelper.read(FileHelper.getResourceFile("XMLHelperTest.novalid"));
        try {
            XMLHelper.validate(xsmFile, xsdFile);
        } catch (SAXParseException spe) {
            assertEquals(8, spe.getLineNumber());
            assertEquals(14, spe.getColumnNumber());
        }
    }

    @Test
    public void testValidate_File_File() throws Exception {
        final File xsdFile = FileHelper.getResourceFile("XMLHelperTest.xsd");
        final File xmlFile = FileHelper.getResourceFile("XMLHelperTest.valid");
        XMLHelper.validate(xmlFile, xsdFile);
    }
}


class Person {
    private String name;
    private String email;
    private Phone phone;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Phone getPhone() {
        return phone;
    }

    public void setPhone(Phone phone) {
        this.phone = phone;
    }
}


class Phone {
    int ddd;
    String number;

    public int getDdd() {
        return ddd;
    }

    public void setDdd(int ddd) {
        this.ddd = ddd;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}
